<?php
/**
* object-oriented file system manipulation as nodes.
* This file belongs to a webappkit package (kit)
* @link http://webappkit.net
* @package pathnodes
* @subpackage common
* @author J.Ducastel <nospam0@ducastel.name>
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*/

/**
* object-oriented file system manipulation as nodes.
* This is the root class
* @author J.Ducastel <nospam0@ducastel.name>
*/
class PathNode {
/*------------------------------------------------------------------------------
                                                                     constructor
------------------------------------------------------------------------------*/
    /**
    * use pathNode::getNode to get an appropriate instance
    * @access private
    */
    function pathNode($path=null) {
        $this->__construct($path);
    }/**/

    /**
    * "real" constructor.
    * use parent::__construct in subclasses to call parent constructor
    * @access private
    */
    function __construct($path=null) {
        // setting own info
        if (is_string($path))
            $this->setInfo($path);
    }
/*------------------------------------------------------------------------------
                                                                  public methods
------------------------------------------------------------------------------*/
    /**
    * returns appropriate instance of pathNode or pathNode subclass
    * @static
    * @param string $path
    * @access public
    * @return pathNode and pathnodes descendant instance
    */
    function & getNode($path) {
        $n=NULL;
        // getting path node heritage class list by specifity desc
        $classes=PathNode::heritage(); //print_r($classes);
        foreach ($classes as $class) {
            //$detection=$class::selfDetector($path)
            $detection=call_user_func(array($class, "selfDetector"),$path);
            if ($detection) {
                // echo "<br />detected $class for $path ! ";
                $n=&new $class($path);
                return $n;
            }
        }
        return $n;
    }/**/

    /**
    * retrieve all subclasses and edventually declare a new subclass
    * If $class
    * @param string $class if provided, register this subclass
    * @param int $specificity 01-99, default 20 higher specificity override more generic classes
    * @access public
    * @static
    * @return array classes name with keys sheme specificity-classname, sorted on keys desc
    */
    function heritage($class=NULL,$specificity=20) {
        static $classes;
        // basic classes
        $classes['01-pathnode']='pathnode';
        //$classes['02-filenode']='filenode';
        //$classes['02-foldernode']='foldernode';
        // adding subclass
        if (is_string($class) and is_int($specificity) and !in_array($class,$classes)) {
            $specificity=sprintf('%02d',$specificity);
            $class=strtolower($class);
            $classes["$specificity-$class"]=$class;
        }
        // sorting by specificity desc
        krsort($classes);
        return $classes;
    }/**/

    /**
    * sets a reference to parent node
    * @param pathNode &$node
    * @access public
    * @return bool
    */
    function setParent(&$node) {
        if (!is_a($node,'pathnode')) return false;
        $this->_parent=&$node;
        return true;
    }/**/

    /**
    *
    * @access public
    * @return string basename
    */
    function getBaseName() {
        return basename($this->path);
    }/**/

    /**
    * returns path from the main script directory
    * @access public
    * @return string
    */
    function getRelativePath() {
        // getting relative path by substracting main script's dirname from absolute path
        return substr($this->getAbsolutePath()
            ,strlen(dirname($_SERVER['SCRIPT_FILENAME']))+1);
    }

    /**
     * get absolute path
     * @return string
     */
    function getAbsolutePath() {
        $realpath=realpath($this->path);
        // a dirty hack for some web hosts using absolute paths without starting /
        if (PHP_OS!='WINNT' and substr($realpath,0,1)!='/')
            $realpath='/'.$realpath;
        return $realpath;
    }

    /**
    * get path as given in constructor
    * @access public
    * @return string
    */
    function getPath() {
        return $this->path;
    }/**/

    /**
    * does the file exists ?
    * @access public
    * @return bool
    */
    function exists() {
        return file_exists($this->path);
    }/**/

    /**
    *
    * @param
    * @access public
    * @return
    * /
    function () {

    }/**/
/*------------------------------------------------------------------------------
                                                                      properties
------------------------------------------------------------------------------*/
    /**
    * @var pathNode reference to parent node
    */
    var $_parent;
    /**
    * @var bool
    */
    //var $exists=false;
    /**
    * @var string file base name (without path)
    */
    //var $basename;
    /**
    * @var string full path as given in constructor
    */
    var $path;
    /**
    * @var string path from current main script
    */
    //var $relative_path;
    /**
    * @var string path from server root
    */
    // var $absolute_path;
/*------------------------------------------------------------------------------
                                                                 private methods
------------------------------------------------------------------------------*/
    /**
    * detects if path applies to self class.
    * subclasses HAVE to implement this method
    * @param string $path
    * @access protected
    * @return bool
    */
    function selfDetector($path) {
        return false;
    }/**/

    /**
    * sets main path information properties from path
    * @param string $path
    * @access protected
    * @return bool
    */
    function setInfo($path) {
        // translating windows path to standard ones
        $path=str_replace('\\','/',$path);
        $this->path=$path;
        return true;
    }/**/
}
?>